import numpy as np
import pandas as pd
from scipy import stats


# 读取 .csv 中的经纬度字段 (字段名: key_lon, key_lat)
def read_lonlat_from_csv(path_csv, key_lon, key_lat):
    df = pd.read_csv(path_csv)
    return np.array(df[key_lon]), np.array(df[key_lat])


# 使用Haversine公式计算两点间距离（以米为单位）
def haversine_distance(lat1, lon1, lat2, lon2):
    R = 6371000  # 地球半径，单位米
    lat1, lon1, lat2, lon2 = map(np.radians, [lat1, lon1, lat2, lon2])
    dlat = lat2 - lat1
    dlon = lon2 - lon1
    a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2)**2
    c = 2 * np.arcsin(np.sqrt(a))
    distance = R * c
    return distance


# 计算指标
def calculate_metrics(error_array):
    max_error = np.max(error_array)
    min_error = np.min(error_array)
    mean_error = np.mean(error_array)
    rmse = np.sqrt(np.mean(error_array ** 2))
    mae = np.mean(np.abs(error_array))
    std = np.std(error_array)
    # 计算95%误差阈值占比
    threshold_95 = np.percentile(np.abs(error_array), 95)
    proportion_95 = np.sum(np.abs(error_array) <= threshold_95) / len(error_array) * 100
    #
    return max_error, min_error, mean_error, rmse, mae, std, proportion_95


# 计算显著性差异
def calculate_significance_difference(error1, error2, method='ttest'):
    if method == 'ttest':
        t_stat, p_value = stats.ttest_rel(error1, error2)
    elif method == 'wilcoxon':
        t_stat, p_value = stats.wilcoxon(error1, error2)
    else:
        raise ValueError("Method must be 'ttest' or 'wilcoxon'")
    # 判断显著性差异
    if p_value < 0.05:
        significance = "显著差异(p<0.05)"
    else:
        significance = "无显著差异(p>=0.05)"
    return t_stat, p_value, significance


def table_err_rmse_mae_std(path_csv_real, key_long_real, key_lati_real,
                           path_csv_aeconvlstm, key_long_aeconvlstm, key_lati_aeconvlstm,
                           path_csv_caekf, key_long_caekf, key_lati_caekf,
                           path_csv_immukf, key_long_immukf, key_lati_immukf):
    print("1. read .csv")
    # 读取真实值和3种算法的经纬度列表
    lon_real, lat_real = read_lonlat_from_csv(path_csv_real, key_long_real, key_lati_real)
    lon_aeconvlstm, lat_aeconvlstm = read_lonlat_from_csv(path_csv_aeconvlstm, key_long_aeconvlstm, key_lati_aeconvlstm)
    lon_caekf, lat_caekf = read_lonlat_from_csv(path_csv_caekf, key_long_caekf, key_lati_caekf)
    lon_immukf, lat_immukf = read_lonlat_from_csv(path_csv_immukf, key_long_immukf, key_lati_immukf)
    print("2. format")
    # 截取相同长度
    lon_real, lat_real = lon_real[1:], lat_real[1:]
    lon_aeconvlstm, lat_aeconvlstm = lon_aeconvlstm[1:], lat_aeconvlstm[1:]
    print("3. calc POS's error")
    # 通过经纬度lon和lat计算位置, 例如通过真实的经纬度lon_real和lat_real计算真实的位置点pos_real
    # 计算真实位置点（这里假设是相对参考点的距离，以第一个点为参考）
    pos_real = np.zeros(len(lon_real))
    pos_aeconvlstm = haversine_distance(lat_real, lon_real, lat_aeconvlstm, lon_aeconvlstm)
    pos_caekf = haversine_distance(lat_real, lon_real, lat_caekf, lon_caekf)
    pos_immukf = haversine_distance(lat_real, lon_real, lat_immukf, lon_immukf)
    print("4. calc metrics of POS's error: RMSE, MAE, Std., 95% error threshold proportion")
    # 计算3种算法(AE-Conv-LSTM, CAEKF, IMMUKF)与真实值(real)位置点误差的RMSE, MAE, Std.和95%误差阈值占比
    # 计算误差
    error_aeconvlstm = pos_aeconvlstm
    error_caekf = pos_caekf
    error_immukf = pos_immukf
    # 计算各项指标
    metrics_aeconvlstm = calculate_metrics(error_aeconvlstm)
    metrics_caekf = calculate_metrics(error_caekf)
    metrics_immukf = calculate_metrics(error_immukf)
    # 计算算法间显著性差异
    print("\n显著性差异分析 (配对t检验):")
    _, p_aeconvlstm_caekf, sig_aeconvlstm_caekf = calculate_significance_difference(error_aeconvlstm, error_caekf)
    _, p_aeconvlstm_immukf, sig_aeconvlstm_immukf = calculate_significance_difference(error_aeconvlstm, error_immukf)
    _, p_caekf_immukf, sig_caekf_immukf = calculate_significance_difference(error_caekf, error_immukf)
    # 打印显著性差异
    print(f"AE-Conv-LSTM vs CAEKF: p-value = {p_aeconvlstm_caekf:.6f}, {sig_aeconvlstm_caekf}")
    print(f"AE-Conv-LSTM vs IMMUKF: p-value = {p_aeconvlstm_immukf:.6f}, {sig_aeconvlstm_immukf}")
    print(f"CAEKF vs IMMUKF: p-value = {p_caekf_immukf:.6f}, {sig_caekf_immukf}")
    # 打印结果表格
    print("\n定位算法性能评估结果:")
    print(
        f"{'算法':<12} {'最大值(m)':<12} {'最小值(m)':<12} {'平均值(m)':<12} {'RMSE(m)':<12} {'MAE(m)':<12} {'Std.(m)':<12} {'95%误差阈值占比(%)':<20}")
    print(f"{'-' * 100}")
    print(f"{'AE-Conv-LSTM':<12} {metrics_aeconvlstm[0]:<12.2f} {metrics_aeconvlstm[1]:<12.2f} "
          f"{metrics_aeconvlstm[2]:<12.2f} {metrics_aeconvlstm[3]:<12.2f} {metrics_aeconvlstm[4]:<12.2f} "
          f"{metrics_aeconvlstm[5]:<12.2f} {metrics_aeconvlstm[6]:<20.2f}")
    print(f"{'CAEKF':<12} {metrics_caekf[0]:<12.2f} {metrics_caekf[1]:<12.2f} "
          f"{metrics_caekf[2]:<12.2f} {metrics_caekf[3]:<12.2f} {metrics_caekf[4]:<12.2f} "
          f"{metrics_caekf[5]:<12.2f} {metrics_caekf[6]:<20.2f}")
    print(f"{'IMMUKF':<12} {metrics_immukf[0]:<12.2f} {metrics_immukf[1]:<12.2f} "
          f"{metrics_immukf[2]:<12.2f} {metrics_immukf[3]:<12.2f} {metrics_immukf[4]:<12.2f} "
          f"{metrics_immukf[5]:<12.2f} {metrics_immukf[6]:<20.2f}")
    # 创建结果字典
    results = {
        'AE-Conv-LSTM': {
            'Max': metrics_aeconvlstm[0],
            'Min': metrics_aeconvlstm[1],
            'Mean': metrics_aeconvlstm[2],
            'RMSE': metrics_aeconvlstm[3],
            'MAE': metrics_aeconvlstm[4],
            'Std': metrics_aeconvlstm[5],
            '95%_threshold_proportion': metrics_aeconvlstm[6]
        },
        'CAEKF': {
            'Max': metrics_caekf[0],
            'Min': metrics_caekf[1],
            'Mean': metrics_caekf[2],
            'RMSE': metrics_caekf[3],
            'MAE': metrics_caekf[4],
            'Std': metrics_caekf[5],
            '95%_threshold_proportion': metrics_caekf[6]
        },
        'IMMUKF': {
            'Max': metrics_immukf[0],
            'Min': metrics_immukf[1],
            'Mean': metrics_immukf[2],
            'RMSE': metrics_immukf[3],
            'MAE': metrics_immukf[4],
            'Std': metrics_immukf[5],
            '95%_threshold_proportion': metrics_immukf[6]
        }
    }
    # 添加显著性差异信息
    significance_results = {
        'AE-Conv-LSTM vs CAEKF': {
            'p_value': p_aeconvlstm_caekf,
            'significance': sig_aeconvlstm_caekf
        },
        'AE-Conv-LSTM vs IMMUKF': {
            'p_value': p_aeconvlstm_immukf,
            'significance': sig_aeconvlstm_immukf
        },
        'CAEKF vs IMMUKF': {
            'p_value': p_caekf_immukf,
            'significance': sig_caekf_immukf
        }
    }
    print("\n显著性差异结果:")
    for comparison, data in significance_results.items():
        print(f"{comparison}: p-value = {data['p_value']:.6f}, {data['significance']}")
    return results, significance_results



if __name__=="__main__":
    # path_csv_dataset_test = "uav_dataset_thph_xy_lonlat_dataset_test.csv"
    # path_csv_caekf = "caekf_out_Xe_Measure4_2_coord_2.csv"
    # path_csv_immukf = "immukf_out_Xe_Measure4_2_coord_2.csv"
    # path_csv_aeconvlstm = "aeconvlstm_out_test_2_coord_2.csv"
    # path_csv_out_table = "table_1_error_rmse_mae_std_95_2.csv"
    # path_csv_out_table_sig = "table_1_error_significance_2.csv"
    # key_long_real, key_lati_real = "lon_smooth", "lat_smooth"
    # key_long_aeconvlstm, key_lati_aeconvlstm = "lon_smooth", "lat_smooth"
    # key_long_caekf, key_lati_caekf = "Longitude", "Latitude"
    # key_long_immukf, key_lati_immukf = "Longitude", "Latitude"
    #
    path_csv_dataset_test = "uav_dataset_interpl_test_2025-10-21.csv"
    path_csv_caekf = "caekf_out_Xe_UAV_Measure_1_test_coord_2025-10-21.csv"
    path_csv_aeconvlstm = "aeconvlstm_out_UAV_Measure_1_test_coord_2025-10-21.csv"
    path_csv_immukf = "immukf_out_Xe_UAV_Measure_1_test_coord_2025-10-21.csv"
    path_csv_out_table = "table_1_error_rmse_mae_std_95_UAV_1_test_coord_2025-10-21.csv"
    path_csv_out_table_sig = "table_1_error_significance_UAV_1_test_coord_2025-10-21.csv"
    key_long_real, key_lati_real = "long_smooth", "lati_smooth"
    key_long_aeconvlstm, key_lati_aeconvlstm = "aeconvlstm_long", "aeconvlstm_lati"
    key_long_caekf, key_lati_caekf = "Longitude", "Latitude"
    key_long_immukf, key_lati_immukf = "Longitude", "Latitude"
    # 计算指标
    results, significance_results = table_err_rmse_mae_std(path_csv_dataset_test, key_long_real, key_lati_real,
                                                           path_csv_aeconvlstm, key_long_aeconvlstm, key_lati_aeconvlstm,
                                                           path_csv_caekf, key_long_caekf, key_lati_caekf,
                                                           path_csv_immukf, key_long_immukf, key_lati_immukf)
    # 将结果转换为DataFrame
    df_results = pd.DataFrame(results).T
    df_results.index.name = 'Algorithm'
    df_results.to_csv(path_csv_out_table)
    print(f"\n结果已保存到: {path_csv_out_table}")
    # 保存显著性差异结果到另一个CSV
    df_sig_results = pd.DataFrame(significance_results).T
    df_sig_results.to_csv(path_csv_out_table_sig)
    print(f"显著性差异结果已保存到: {path_csv_out_table_sig}")